/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package phys;

import gui.PhysicsPanel;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import spring.Element;
import vec.Vector3f;

/**
 *
 * @author Vic
 */
public class CollisionResolver {

    static Rectangle bounds;
    static final List<Element> colidables = Collections.synchronizedList(new ArrayList<Element>());

    public static void resolve() {
        synchronized (colidables) {
            for (Element c : colidables) {
                if (c.isPassive()) {
                    continue;
                }
                Rectangle shape = c.getBounds();
//                System.out.println("Object = "+ c.getClass());
//                System.out.println("state = " + c.getState());
//                System.out.println("shape = " + shape);
//                System.out.println("bounds = " + bounds);
                if (shape.getMaxX() > bounds.getMaxX()) {
                    float v2x = -Math.abs(c.getState().velocity.x) / 1.2f;
//                    float p2x = (float) bounds.getMaxX() - (float) shape.getWidth() / 2;
                    Vector3f displacement = new Vector3f(v2x - c.getState().velocity.x, 0, 0);
                    displacement.scale(c.getState().mass);
                    c.getState().impulse.add(displacement);
                    //System.out.println(c.getState());

                    System.out.println("Bounce left");
                } else if (shape.getMinX() < bounds.getMinX()) {
                    float v2x = Math.abs(c.getState().velocity.x) / 1.2f;

                    Vector3f displacement = new Vector3f(v2x - c.getState().velocity.x, 0, 0);
                    displacement.scale(c.getState().mass);
                    c.getState().impulse.add(displacement);
//                    c.getState().position.x = (float) shape.getWidth() / 2;
                    System.out.println("Bounce right");
                }
                if (shape.getMaxY() > bounds.getMaxY()) {
                    float v2y = -Math.abs(c.getState().velocity.y) / 1.2f;
//                    c.getState().position.y = (float) bounds.getMaxY() - (float) shape.getHeight() / 2;
                    Vector3f displacement = new Vector3f(0, v2y - c.getState().velocity.y, 0);
                    displacement.scale(c.getState().mass);
                    c.getState().impulse.add(displacement);
                    System.out.println("Bounce down");
                } else if (shape.getMinY() < bounds.getMinY()) {
                    float v2y = Math.abs(c.getState().velocity.y) / 1.2f;
                    Vector3f displacement = new Vector3f(0, v2y - c.getState().velocity.y, 0);
                    displacement.scale(c.getState().mass);
                    c.getState().impulse.add(displacement);
//                    c.getState().position.y = (float) shape.getHeight() / 2;
                    System.out.println("Bounced up");
                }
                List<Element> unCollided = new ArrayList<>(colidables);
                unCollided.remove(c);
                for (Element other : unCollided) {
                    Rectangle otherShape = other.getBounds();
                    if (shape.intersects(otherShape)) {
                        System.err.println("Collision");
                        Vector3f displacement = new Vector3f((float) (otherShape.getCenterX() - shape.getCenterX()),
                                (float) (otherShape.getCenterY() - shape.getCenterY()), 0);
                        float slope = (float) Math.abs(shape.getMaxY() / shape.getMaxX());
                        Vector3f cv2 = (Vector3f) c.getState().velocity.clone(),
                                ov2 = (Vector3f) other.getState().velocity.clone();
                        if (displacement.x > 0) {
                            if (displacement.y / displacement.x > slope) {
                                System.out.println("collide bounce up");
                                cv2.y = -Math.abs(c.getState().velocity.y);
                                ov2.y = +Math.abs(other.getState().velocity.y);
                            } else if (displacement.y / displacement.x > -slope) {
                                System.out.println("collide bounce right ");
                                cv2.x = -Math.abs(c.getState().velocity.x);
                                ov2.x = Math.abs(other.getState().velocity.x);
                            } else {
                                System.out.println("collide boune down ");
                                cv2.y = +Math.abs(c.getState().velocity.y);
                                ov2.y = -Math.abs(other.getState().velocity.y);
                            }
                        } else if (displacement.y / displacement.x < -slope) {
                            System.out.println("collide bounce up");
                            cv2.y = -Math.abs(c.getState().velocity.y);
                            ov2.y = +Math.abs(other.getState().velocity.y);
                        } else if (displacement.y / displacement.x < slope) {
                            System.out.println("bounce left ");
                            cv2.x = +Math.abs(c.getState().velocity.x);
                            ov2.x = -Math.abs(other.getState().velocity.x);
                        } else {
                            System.out.println("boune down");
                            cv2.y = +Math.abs(c.getState().velocity.y);
                            ov2.y = -Math.abs(other.getState().velocity.y);
                        }
                        cv2.sub(c.getState().velocity);
                        cv2.scale(c.getState().mass);
                        c.getState().impulse.add(cv2);

                        ov2.sub(other.getState().velocity);
                        ov2.scale(other.getState().mass);
                        other.getState().impulse.add(ov2);
                    }
                }

            }
        }
    }

    public static synchronized void add(Element aThis) {
        colidables.add(aThis);
        System.err.println(aThis);
    }

    public static synchronized void setBounds(Rectangle bounds) {
        CollisionResolver.bounds = bounds;
    }

    public static void removeAll(Class clazz) {
        ArrayList toRemove = new ArrayList();
        for (Object obj : colidables) {
            if (clazz.isInstance(obj)) {
                toRemove.add(obj);
            }
        }
        colidables.removeAll(toRemove);
    }
}
